//
//  InitViewController.swift
//  SyanYan
//
//  Created by Yanyan Jiang on 2018/7/8.
//  Copyright © 2018年 Yanyan Jiang. All rights reserved.
//

import UIKit

class InitViewControllerOne: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //初始化原则、便捷初始化、初始化继承、延缓加载属性、反初始化
        //初始化 initialization
        //OC中对象初始化，类在构建对象的时候，对对象进行初始化的一个操作，swift如果谈到初始化就不光指这些，任何东西都需要初始化，比如说一个变量就需要初始化，我们谈变变量初始化的时候那她的意思就是说变量在赋初始值的时候这个操作就属于初始化的这个过程比如说 var a = 2 这句话就相当于把a给进行了初始化，你对一个结构体或者一个对象的属性赋初始值的时候这个时候也叫初始化，不要只想着对象的初始化 Every value must be initialization before it is used 每个值在使用之前都必须进行初始化，这些如果做不到编译器在编译的时候会报错
        //一般变量的初始化
        var message: String
        //我们并没有给他赋初始值，注意swift中一个变量如果你没有给它赋初始值，它不会像一般语言中的一个默认的值，比方说  var a: Double a不会有默认值，除了可能值变量有初始值nil 一般变量是没有的
        //if sessionStarted{
           // message = "欢迎收看 swift 进阶"
        //}
        //print(message)
        //error: variable "message" used before being initialized 违背了变量在使用之前对它进行初始化的原则
        //
        //初始化方法应该将一个实例或者结构体彻底初始化 init(){...}
//        let label = UILabel()
        //let magenta = Color2(red: 1.0, green: 0.0, blue: 1.0)
        //let black = Color3()
        //
        //类初始化、对象初始化 Class Initialization
        //类初始化与结构体几乎是一样的,因为结构体没有类继承的问题，而我们的类有继承的问题
        //
        //其实一个类里面可以有多个初始化方法
        //初始化方法内调 initializer Delegation,多个初始化方法中可能会有调用
        //Designated设计好的或者主的初始化方法它的责任就是要完全的对当前类的储值属性进行初始赋值，然后将父类的这些赋值转接给或者说内调或者说转调给你的父类的方法让你的父类将你的父类的这些储值属性进行初始化，如果你的父类还有父类，那你的父类再转接给你的父类的父类进行属性的初始化；初始化自己类内的储值属性，将继承过来的属性转接给父类去执行
        //Convenience 便捷方法，写便捷初始化方法减少一些没有必要初始化的参数，将一些默认的值传给一些我们设计好的主初始化方法，便捷方法会调用当前类的主初始化方法；区别便捷方法只能转接调用同类的主初始化方法或者是其他方法，他不能调父类的，我的主方法只能调父类的主方法它不能调同级的方法
        
        //Base Class
        //
        //
        //
        //Super Class
        //
        //
        //
        //Class
        //
        //
        //
        //
        //
        //
        //
        //
        //
        
        
        

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
}

//结构体初始化
struct Color {
    let red, green, blue: Double
    mutating func validateColor(){
        
    }
    init(grayScale: Double) {
        red = grayScale //如果red储值属性不赋值会报错 error: variable 'self.red' used before being initialized  变量‘self.red’在使用前未被初始化
        green = grayScale
        //validateColor()//'self' used before all stored properties are initialized
        blue = grayScale
        validateColor()
    }
}

//如果你不写初始化方法的话系统会自动帮你生成一个初始化函数,我们管它叫成员初始化函数Memberwise Initializers,这个初始化函数会让你给没有赋值的储值属性赋值，
struct Color2 {
    let red, green, blue: Double
}

//结构体的所有属性也可以给个默认值，系统在给你生成初始化方法的时候就给你生成一个无参数的初始化方法
struct Color3 {
    let red = 0.0, green = 0.0, blue = 0.0
}


class CarCar {
    var paintColor: Color
    func fillGasTank() -> () {
        
    }
    init(color: Color) {
        paintColor = color
        fillGasTank()
    }
}


//此类不管你是继承的还是自己本身的属性都已经初始化了
class RaceCar: CarCar {
    var hasTurbo: Bool//有没有涡轮，跑车是一定有涡轮的
    override func fillGasTank() {
        //我们在初始化RaceCar的时候 并不会调父类的fillGasTank(),只会调 RaceCar类的fillGasTank()方法
    }
    init(color: Color, turbo: Bool) {
        hasTurbo = turbo //Property 'self.hasTurbo' not initialized at super.init call
        super.init(color: color)//这句话要写到下面，不能像oc那样写到上面，如果写到上面它会带来内存的一些安全的问题，为什么会出现问题，我们接下来加一个函数，模拟这个错误的呈现，RaceCar还没有完全初始化就使用了这个对象所以会报错，这就是初始化的继承
        hasTurbo = turbo //Property 'self.hasTurbo' not initialized at super.init call
    }
    convenience override init(color: Color) {
        self.init(color: color, turbo: true)
    }
    convenience init() {
        self.init(color: Color(grayScale: 0.4))
    }

}
